import { createRouter, createWebHistory } from 'vue-router'
import { staticRoutes, asyncRoutes } from './routes'
import { useAuthStore } from '@/stores/authStore'

const router = createRouter({
  history: createWebHistory(),
  routes: staticRoutes,
})

// 白名单 过滤出所有public为true的路由并且把name添加到白名单中
const whiteList = staticRoutes.filter((r) => r.meta?.['public']).map((r) => r.name)

// 标记动态路由是否已添加，防止重复添加
let dynamicRoutesAdded = false

// 全局前置路由守卫
router.beforeEach(async (to, _, next) => {
  // 在路由守卫中初始化 pinia 是为了确保 页面刷新或路由切换能及时获取到用户认证状态 从而避免丢失及后续逻辑无法判断
  // 放在外面简单场景可以，但如果在处理 异步验证 页面刷新 等场景 路由守卫无法保证认证状态等
  const authStore = useAuthStore()
  const token = authStore.token
  // 获取用户角色
  const userRoles = authStore.userInfo?.roles || []

  // 已登录访问登录页，跳转首页
  if (token && to.name === 'login') {
    next({ name: 'home' })
    return
  }

  // 白名单直接放行
  if (whiteList.includes(to.name as string)) {
    next()
    return
  }

  // 未登录，跳转登录页
  if (!token) {
    next({ name: 'login', query: { redirect: to.fullPath } })
    return
  }

  // 动态路由只添加一次
  if (!dynamicRoutesAdded) {
    // 前端使用本地 asyncRoutes
    const allowedRoutes = asyncRoutes.filter((route) => {
      // 没有 roles 限制的路由默认所有人可访问
      if (!route.meta?.roles) return true
      // 有 roles 限制的路由，用户角色需有交集
      return route.meta.roles.some((role: string) => userRoles.includes(role))
    })
    allowedRoutes.forEach((route) => {
      router.addRoute(route)
    })
    // 在这里添加404路由 放在动态路由最后
    router.addRoute({
      path: '/:pathMatch(.*)*',
      name: 'not-found',
      component: () => import('@/views/NotFoundView.vue'),
      meta: {
        title: '404',
        public: true,
      },
    })
    dynamicRoutesAdded = true
    // 必须重新进入一次目标路由，确保新路由生效
    next({ ...to, replace: true })
    return
  }

  // 权限校验
  if (
    Array.isArray(to.meta?.['roles']) &&
    !to.meta['roles'].some((role: string) => userRoles.includes(role))
  ) {
    next({ name: '403' })
    return
  }

  // 其他情况正常放行
  next()
})

export default router
